/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { IConstantResolver } from '../interface/IConstantResolver';
import { BaseAnalyzeResult, TsAstUtil } from '../../../framework';

/**
 * Constant analyzer
 * Responsible for parsing constant references in analysis results
 */
export class ConstantAnalyzer {
  private constantResolver: IConstantResolver;
  constructor(constantResolver: IConstantResolver) {
    this.constantResolver = constantResolver;
  }

  /**
   * Parse constants in analysis results
   * @param analyzeResults Analysis result collection
   */
  parseConstants(analyzeResults: Set<BaseAnalyzeResult>): void {
    analyzeResults.forEach((item) => {
      this.parseResult(item);
    });
  }

  /**
   * Parse all properties in a single result object
   * @param result Analysis result object
   */
  private parseResult(result: BaseAnalyzeResult): void {
    if (!result.sourceFilePath) {
      return;
    }

    Object.getOwnPropertyNames(result).forEach((key: string) => {
      let propertyValue = Reflect.get(result, key);
      propertyValue = this.parsePropertyValue(result.sourceFilePath!, propertyValue);

      if (propertyValue === '') {
        throw new Error(`Constants value cannot be an empty string, filePath: ${result.sourceFilePath}`);
      }

      Reflect.set(result, key, propertyValue);
    });
  }

  /**
   * Parse a single property value
   * @param filePath File path
   * @param propertyValue Property value
   * @returns Parsed value
   */
  private parsePropertyValue(filePath: string, propertyValue: any): any {
    // Get the source file object
    const sourceFile = TsAstUtil.getSourceFile(filePath);
    return this.constantResolver.resolveConstant(propertyValue, sourceFile, filePath);
  }
}
